# Copyright (c) [Year] [name of copyright holder]
#   [Software Name] is licensed under Mulan PSL v2.
#   You can use this software according to the terms and conditions of the Mulan PSL v2.
#   You may obtain a copy of Mulan PSL v2 at:
#            http://license.coscl.org.cn/MulanPSL2
#   THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#   See the Mulan PSL v2 for more details. 

import pygame,sys,random

SCREEN_X=600 # 屏幕的长度
SCREEN_Y=600 # 屏幕的宽度

class Snake(object): #Snake类
    def __init__(self):
        self.direction=pygame.K_RIGHT # 初始化方向向右
        self.canChangeDirection=True
        self.body=[] # 蛇的身体
        for _ in range(5):
            self.addnode() # 初始化身体长度：5个方块

    def addnode(self): # 增加一个方块
        left,top=0,0
        if self.body:
            left,top=self.body[0].left,self.body[0].top
        node=pygame.Rect(left,top,25,25)
        # 通过按➡，⬅，⬆，⬇控制方向
        if self.direction==pygame.K_LEFT:
            node.left-=25
        elif self.direction==pygame.K_RIGHT:
            node.left+=25
        elif self.direction==pygame.K_UP:
            node.top-=25
        elif self.direction==pygame.K_DOWN:
            node.top+=25
        self.body.insert(0,node) # 在头部插入方块

    def delnode(self):
        self.body.pop() #删除尾部方块

    def isdead(self): #蛇是否死亡
        if self.body[0].x not in range(SCREEN_X)\
        or self.body[0].y not in range(SCREEN_Y): #蛇出界：x,y值不在屏幕的长度,宽度范围里
            return True
        return False

    def move(self): #蛇移动
        self.addnode()
        self.delnode()

    def changedirection(self,curkey): #改变方向：如果正在向上想改变方向只能向左，右走，不能向上，下走
        if not self.canChangeDirection:
            return None
        LR=[pygame.K_LEFT,pygame.K_RIGHT]#左右方向
        UD=[pygame.K_UP,pygame.K_DOWN]#上下方向
        if curkey in LR+UD:
            if (curkey in LR) and (self.direction in LR):
                return
            if (curkey in UD) and (self.direction in UD):
                return
            self.direction=curkey#改变方向

class Food(object):# Food类
    def __init__(self):
        self.rect=pygame.Rect(-25,0,25,25)

    def remove(self):
        self.rect.x=-25

    def set(self):
        if self.rect.x==-25:
            allpos=[]#所有可能的方位 间距为25px
            for pos in range(25,SCREEN_X-25,25):
                allpos.append(pos)
            self.rect.left=random.choice(allpos)
            self.rect.top=random.choice(allpos)

def show_text(screen,pos,text,color,font_bold=False,font_size=60,font_italic=False):# 显示文字
    cur_font=pygame.font.SysFont("宋体",font_size)
    cur_font.set_bold(font_bold)
    cur_font.set_italic(font_italic)
    text_fmt=cur_font.render(text,1,color)
    screen.blit(text_fmt,pos)

def main(): #主函数
    pygame.init()
    screen_size=(SCREEN_X,SCREEN_Y)#屏幕大小
    screen=pygame.display.set_mode(screen_size)
    pygame.display.set_caption('SnakeGame')#标题
    clock=pygame.time.Clock()
    scores=100#分值，当分值为0时蛇死亡
    scorechange=1
    best_score=0#最高分
    isdead=0#蛇是否死亡
    isrunning=1#游戏是否正在运行
    snake=Snake()
    food=Food()

    while True:
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                print('best score: %d'%best_score)
                sys.exit()
            if event.type==pygame.KEYDOWN:
                snake.changedirection(event.key)
                if event.key==pygame.K_SPACE and isdead:
                    print('best score: %d'%best_score)
                    return main() #重新开始游戏
            if event.type==pygame.MOUSEBUTTONDOWN:#鼠标键
                isrunning=1-isrunning#改变蛇的运动状态
                scorechange=1-scorechange
                snake.canChangeDirection=False
        screen.fill((255,255,255))#屏幕底色为白色
        if not isdead and isrunning:
            snake.move()
        for rect in snake.body:
            pygame.draw.rect(screen,(20,220,39),rect,0)
        isdead=snake.isdead()
        if isdead or scores<=0: #死亡
            show_text(screen,(100,200),'YOU DEAD!',(227,29,18),False,100)#显示死亡文本
            show_text(screen,(150,260),'press space to try again...',(0,0,22),False,30)
            scores=0
        if food.rect==snake.body[0]:
            scores+=50
            food.remove()
            snake.addnode()
        food.set()
        pygame.draw.rect(screen,(136,0,21),food.rect,0)
        show_text(screen,(50,500),'Scores: '+str(scores),(223,223,223))#显示分数文本
        pygame.display.update()
        clock.tick(10)
        best_score=max(best_score,scores)
        scores-=scorechange

if __name__ == '__main__':
    main()